// Copyright ©2011-2012 Kris Maglione <maglione.k@gmail.com>
// Copyright ©2012 Mozilla Corporation
//
// This work is licensed for reuse under an MIT license. Details are
// given in the LICENSE file included with this file.
"use strict";

const { classes: Cc, interfaces: Ci, results: Cr, utils: Cu } = Components;
const Cm = Components.manager.QueryInterface(Ci.nsIComponentRegistrar);

var { BLOCKLIST_PREF, Services, _, debug, fixURL, isLocalProtocol, isUIProtocol, locations, log, prefs, refreshCompartments, reportError, wrapCallback } = Cu.import("resource://exttest/exttest.jsm", {});
const { jQueryCheck } = Cu.import("resource://exttest/jquery-wrapper.jsm", {});
const { XPCOMUtils }  = Cu.import("resource://gre/modules/XPCOMUtils.jsm", {});

var EXPORTED_SYMBOLS = ["Globals"];

function EvalCheck(name, test) {
    Check.method = name;
    Check.id = EvalCheck.id++;
    Check.test = function test(arg) {
        if (typeof arg !== "function")
            return "setTimeout.eval";
        return false
    }
    if (test)
        Check.test = test;

    Check.locations = {};

    function Check(orig) {
        let args = Array.slice(arguments, 1);
        try {
            let res = Check.test.apply(Check, args);
            if (res) {
                let caller = Components.stack.caller;
                let loc = fixURL(caller.filename) + ":" + caller.lineNumber;

                if (!Check.locations.hasOwnProperty(loc) && prefs.console.get(Check.method, true))
                    log(_("unsafeUse", Check.method) +
                        (typeof res !== "boolean" ? " (" + _.apply(null, Array.concat(res)) + ")" : ""),
                        null, caller);

                Check.locations[loc] = 1 + (Check.locations[loc] || 0);
                if (orig && orig.exttestLocations)
                    orig.exttestLocations[loc] = 1 + (orig.exttestLocations[loc] || 0);
            }
        }
        catch (e) {
            Cu.reportError(e);
        }
        return orig.apply(this, args);
    }
    return Check;
}

const Wrappers = {
    setInterval: EvalCheck("setInterval"),
    setTimeout: EvalCheck("setTimeout")
};

const Globals = {
    mangle: function mangle(window) {
        for (let [method, wrapper] in Iterator(Wrappers)) {
            let orig = window[method];
            window[method] = wrapper.bind(window, orig);
            window[method].exttestLocations = orig.exttestLocations = {};
        }
    }
};

Services.pref.addObserver(BLOCKLIST_PREF, function observe(branch, topic, pref) {
    if (pref == BLOCKLIST_PREF)
        refreshBlocklist();
}, false);
